﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Pixysoft.Framework.Verifications;
using Pixysoft.Tools;

namespace Pixysoft.Weblications.Sango.Battle
{
    class RveStageController
    {
        /// <summary>
        /// 已经加入群战的用户列表，防止用户反复加入
        /// </summary>
        Dictionary<string, long> joinedUsers = new Dictionary<string, long>();
        /// <summary>
        /// 群战房间
        /// </summary>
        List<RveStageTeam> teams = new List<RveStageTeam>();

        private static ReaderWriterLock locker = new ReaderWriterLock();
        private static volatile RveStageController instance;
        private static object syncRoot = new object();

        public static RveStageController Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                        {
                            instance = new RveStageController();
                        }
                    }
                }

                return instance;
            }
        }

        /// <summary>
        /// 是否已经加入群战
        /// </summary>
        /// <param name="usercode"></param>
        /// <returns></returns>
        public bool HasJoinStage(string usercode)
        {
            locker.AcquireReaderLock(Timeout.Infinite);

            try
            {
                return joinedUsers.ContainsKey(usercode);
            }
            finally
            {
                locker.ReleaseReaderLock();
            }
        }

        /// <summary>
        /// 获取战斗房间列表
        /// </summary>
        /// <param name="stageserialcode"></param>
        /// <param name="sectionserialcode"></param>
        /// <returns></returns>
        public List<RveStageTeam> GetTeams(long stageserialcode, long sectionserialcode)
        {
            List<RveStageTeam> list = new List<RveStageTeam>();

            locker.AcquireReaderLock(Timeout.Infinite);

            try
            {
                foreach (RveStageTeam team in teams)
                {
                    if (team.Stage.Stageserialcode != stageserialcode)
                        continue;
                    if (team.Section.Sectionserialcode != sectionserialcode)
                        continue;
                    list.Add(team);
                }
                return list;
            }
            finally
            {
                locker.ReleaseReaderLock();
            }
        }

        /// <summary>
        /// 创建战斗房间
        /// </summary>
        /// <param name="profile"></param>
        /// <param name="stage"></param>
        /// <param name="section"></param>
        /// <returns></returns>
        public RveStageTeam CreateStageRoom(Entities.Usr_Profile profile, Entities.War_Stage stage, Entities.Sys_Section section, long battledate)
        {
            locker.AcquireWriterLock(Timeout.Infinite);

            try
            {
                if (joinedUsers.ContainsKey(profile.Usercode))
                    throw Exceptions.VerificationFailedException(profile, stage, section, battledate);

                RveStageTeam team = new RveStageTeam(stage, section, profile, battledate);

                teams.Add(team);

                joinedUsers.Add(profile.Usercode, team.Roomcode);

                return team;
            }
            finally
            {
                locker.ReleaseWriterLock();
            }
        }

        /// <summary>
        /// 加入已经存在的房间
        /// 如果房间不存在，返回null
        /// 如果用户已经加入房间，抛出exception
        /// </summary>
        /// <param name="roomcode"></param>
        /// <param name="usercode"></param>
        /// <returns></returns>
        public RveStageTeam TryJoinStage(long roomcode, string usercode)
        {
            locker.AcquireWriterLock(Timeout.Infinite);

            try
            {
                if (joinedUsers.ContainsKey(usercode))
                    throw Exceptions.VerificationFailedException(roomcode, usercode);

                RveStageTeam team = UnsafeTrySearchTeam(roomcode);

                if (team == null)
                {
                    return null;
                }

                team.Join(usercode);

                joinedUsers.Add(usercode, team.Roomcode);

                return team;
            }
            finally
            {
                locker.ReleaseWriterLock();
            }
        }

        /// <summary>
        /// 离开房间
        /// </summary>
        /// <param name="roomcode"></param>
        /// <param name="usercode"></param>
        /// <returns></returns>
        public RveStageTeam TryLeaveStage(string usercode)
        {
            locker.AcquireWriterLock(Timeout.Infinite);

            try
            {
                //有可能房间主人主动关闭房间

                if (!joinedUsers.ContainsKey(usercode))
                    return null;

                long roomcode = joinedUsers[usercode];

                RveStageTeam team = UnsafeTrySearchTeam(roomcode);

                if (team == null)
                {
                    return null;
                }

                team.Leave(usercode);

                joinedUsers.Remove(usercode);

                return team;
            }
            finally
            {
                locker.ReleaseWriterLock();
            }
        }

        /// <summary>
        /// 关闭战斗房间
        /// 只有房间主人才能关闭
        /// </summary>
        /// <returns></returns>
        public RveStageTeam TryCloseStageRoom(string usercode)
        {
            locker.AcquireWriterLock(Timeout.Infinite);

            try
            {
                if (!joinedUsers.ContainsKey(usercode))
                    return null;

                long roomcode = joinedUsers[usercode];

                RveStageTeam team = UnsafeTrySearchTeam(roomcode);

                if (team == null)
                    return null;

                if (!team.Creator.Usercode.Equals(usercode, StringComparison.OrdinalIgnoreCase))
                    throw Exceptions.VerificationFailedException(roomcode, usercode);

                teams.Remove(team);

                foreach (string teamUsercode in team.Profiles)
                {
                    joinedUsers.Remove(teamUsercode);
                }

                return team;
            }
            finally
            {
                locker.ReleaseWriterLock();
            }
        }

        /// <summary>
        /// 获取rve队伍
        /// </summary>
        /// <param name="usercode"></param>
        /// <returns></returns>
        public RveStageTeam TryGetStage(string usercode)
        {
            locker.AcquireReaderLock(Timeout.Infinite);

            try
            {
                if (!joinedUsers.ContainsKey(usercode))
                    return null;

                long roomcode = joinedUsers[usercode];

                RveStageTeam team = UnsafeTrySearchTeam(roomcode);

                return team;
            }
            finally
            {
                locker.ReleaseReaderLock();
            }
        }

        /// <summary>
        /// 根据主键获取房间
        /// </summary>
        /// <param name="roomcode"></param>
        /// <returns></returns>
        public RveStageTeam TryGetStageTeam(long roomcode)
        {
            locker.AcquireReaderLock(Timeout.Infinite);

            try
            {
                RveStageTeam team = UnsafeTrySearchTeam(roomcode);

                if (team == null)
                    return null;

                return team;
            }
            finally
            {
                locker.ReleaseReaderLock();
            }
        }

        private RveStageTeam UnsafeTrySearchTeam(long roomcode)
        {
            foreach (RveStageTeam team in teams)
            {
                if (team.Roomcode == roomcode)
                    return team;
            }

            return null;
        }


        /// <summary>
        /// 查询到期的队伍，移除并返回
        /// </summary>
        /// <returns></returns>
        public List<RveStageTeam> Dispatch()
        {
            List<RveStageTeam> list = new List<RveStageTeam>();

            locker.AcquireWriterLock(Timeout.Infinite);

            try
            {
                foreach (RveStageTeam team in teams)
                {
                    if (team.Battledate < GlobalTimer.Instance.ToTimeSequence())
                    {
                        list.Add(team);
                    }
                }

                foreach (RveStageTeam team in list)
                {
                    teams.Remove(team);

                    foreach (string teamUsercode in team.Profiles)
                    {
                        joinedUsers.Remove(teamUsercode);
                    }
                }

                return list;
            }
            finally
            {
                locker.ReleaseWriterLock();
            }
        }

    }
}
